﻿using System;
using System.Linq;
using System.Threading.Tasks;
using CSRedis;
using NetMicro.Cache.RedisProvider;

namespace NetMicro.Cache.DelayBus
{
    /// <summary>
    /// 桶
    /// </summary>
    public static class Bucket
    {
        /// <summary>
        /// 桶前缀
        /// </summary>
        private const string queuePrefix = "delay-queue-bucket:";



        /// <summary>
        /// 推送消息进桶
        /// </summary>
        /// <param name="topic">主题</param>
        /// <param name="jobId">任务编号</param>
        /// <param name="delay">延迟时间</param>
        /// <returns>处理结果</returns>
        public static Task<long> PushJobToBucketAsync(this IRedisCache redisCache, string topic, string jobId, TimeSpan delay)
        {
            long delaySec = GetDelaySeconds(delay);
            redisCache.StartPipe();
            return redisCache.ZAddAsync($"{queuePrefix}{topic}", scoreMembers: new ZMemberScore
            {
                Member = jobId,
                Score = Convert.ToDecimal(delaySec),
            });
        }

        /// <summary>
        /// 推送消息进桶
        /// </summary>
        /// <param name="topic">主题</param>
        /// <param name="jobId">任务编号</param>
        /// <param name="delay">延迟时间</param>
        /// <returns>处理结果</returns>
        public static void PushJobToBucket(this CSRedisClientPipe<string> clientPipe, string topic, string jobId, TimeSpan delay)
        {
            long delaySec = GetDelaySeconds(delay);
            clientPipe.ZAdd($"{queuePrefix}{topic}", (Convert.ToDecimal(delaySec), jobId));
        }
        /// <summary>
        /// 得到的时间戳
        /// </summary>
        /// <param name="delay"></param>
        /// <returns></returns>
        public static long GetDelaySeconds(TimeSpan delay)
        {
            return new DateTimeOffset(DateTime.Now.Add(delay).ToUniversalTime()).ToUnixTimeSeconds();
        }

        /// <summary>
        /// 得到的时间
        /// </summary>
        /// <param name="ttr"></param>
        /// <param name="scope"></param>
        /// <returns></returns>
        public static DateTime GetDelayTTRTime(TimeSpan ttr, decimal scope)
        {
            decimal ttrTimeStamp = scope + Convert.ToDecimal(ttr.TotalSeconds);
            return DateTimeOffset.FromUnixTimeSeconds(long.Parse(ttrTimeStamp.ToString("0000"))).LocalDateTime;
        }
        /// <summary>
        /// 获取已到过期时间的任务
        /// </summary>
        /// <param name="redisCache"></param>
        /// <param name="topic"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public static async Task<string> GetExpireJobsAsync(this IRedisCache redisCache, string topic, int limit)
        {
            return (await redisCache.ZRangeByScoreAsync($"{queuePrefix}{topic}", 0.0m, GetDelaySeconds(TimeSpan.Zero), limit))?.FirstOrDefault();
        }



        /// <summary>
        /// 移除任务
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="jobId"></param>
        /// <returns></returns>
        public static Task<long> RemoveJobAsync(this IRedisCache redisCache, string topic, string jobId)
        {
            return redisCache.ZRemAsync($"{queuePrefix}{topic}", member: jobId);
        }

        /// <summary>
        /// 移除任务
        /// </summary>
        /// <param name="clientPipe"></param>
        /// <param name="topic"></param>
        /// <param name="jobId"></param>
        public static void RemoveJob(this CSRedisClientPipe<string> clientPipe, string topic, string jobId)
        {
            clientPipe.ZRem($"{queuePrefix}{topic}", jobId);
        }
    }
}
